home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / CUGUK / PROG_TOO / C023A.ZIP / PART2 / ZRES.C < prev    next >
Text File  |  1990-01-31  |  16KB  |  655 lines

  1. /*
  2.  * zresolve - link preprocessor to resolve library references
  3.  *            this version uses modified zlink to allow loading
  4.  *            of multiple modules from one file
  5.  *
  6.  * Three tables used in this program:
  7.  *
  8.  *  the symbol table holds all symbols used in the program to be linked,
  9.  *  both defined and undefined.  The aim is to define all these symbols.
  10.  *
  11.  *  the library table contains all the symbols defined in the library (as
  12.  *  listed in the index file) together with a pointer to the module in which
  13.  *  they are defined.
  14.  *
  15.  *  the index file contains, for each module, a list of all the symbols
  16.  *  defined and required.  This list is used to update the symbol table
  17.  *  when a library module is loaded.
  18.  *
  19.  * Bug reports, bug fixes and comments should be addressed to the author:
  20.  *
  21.  *    R M Yorston
  22.  *    1 Church Terrace
  23.  *    Lower Field Road
  24.  *    Reading
  25.  *    RG1 6AS
  26.  *
  27.  */
  28.  
  29. #include <stdio.h>
  30. #include <string.h>
  31.  
  32. /* symbol type flags */
  33. #define DEFINED 0
  34. #define UNDEFINED 1
  35.  
  36. #define FALSE 0
  37. #define TRUE 1
  38.  
  39. #define CR 13
  40. #define NULL 0
  41.  
  42. /* symbol table format */
  43. #define NAME        0
  44. #define TYPE        17
  45. #define SYMREC        18
  46.  
  47. /* symbol table parameters */
  48. #define NUMENT        700
  49. #define STARTTAB    Symtab
  50. #define ENDTAB        (STARTTAB + ((NUMENT-1)*SYMREC))
  51. #define SYMSIZE        (NUMENT*SYMREC)
  52.  
  53. /* library table format */
  54. #define LIBNAME        0
  55. #define MODULE        17
  56. #define LIBREC        18
  57.  
  58. /* library table parameters */
  59. #define LIBENT        500
  60. #define STARTLIB    Libtab
  61. #define ENDLIB        (STARTLIB + ((LIBENT-1)*LIBREC))
  62. #define LIBSIZE        (LIBENT*LIBREC)
  63.  
  64. /* index table format */
  65. #define IXNAME        0
  66. #define IXTYPE        17
  67. #define IXREC        18
  68.  
  69. /* index table parameters */
  70. #define IXENT        600
  71. #define IXSIZE        (IXENT*IXREC)
  72.  
  73. /* maximum size of symbol */
  74. #define NAMEMAX 16
  75.  
  76. char *Symtab ;            /* pointer to start of symbol table */
  77. char *Libtab ;            /* pointer to start of library table */
  78. char *Index ;            /* pointer to start of index table */
  79. int  *Module ;            /* array of pointers to module names */
  80. int  *Objptr ;            /* array of pointers to index chains */
  81. int  *Rec ;                /* array of starting records for each module */
  82. int  *Off ;                /* array of offsets into records */
  83. int  Nmod ;                /* number of modules in library */
  84.  
  85. int Ixused ;            /* number of entries used in index table */
  86. int Libused ;            /* number of entries used in library table */
  87. int Symused ;            /* number of entries used in symbol table */
  88.  
  89. int Plotflag ;            /* TRUE if a plotting function has been loaded */
  90. int Printflag ;            /* TRUE if _printf has to be loaded */
  91. int Scanflag ;            /* TRUE if _scanf has to be loaded */
  92. int Floatflag ;            /* TRUE if a floating point function has been loaded */
  93. int Ploadflag ;            /* TRUE if printf2 has been loaded */
  94. int Sloadflag ;            /* TRUE if scanf2 has been loaded */
  95.  
  96. int Libfile ;            /* file descriptor for library */
  97. int Subfile ;            /* file descriptor for submit file */
  98. int Objfile ;            /* file descriptor for .OBJ file */
  99.  
  100. char Command[128];        /* array in which command is built */
  101.  
  102. main( argc, argv)
  103. int argc ;
  104. char **argv ;
  105. {
  106.     char temp[40] ;
  107.     int i ;
  108.  
  109.     /* allocate space for symbol tables and fill them with zeroes */
  110.     Symtab = zalloc(SYMSIZE) ;
  111.     Libtab = zalloc(LIBSIZE) ;
  112.     Index = zalloc(IXSIZE) ;
  113.  
  114.     /* check arguments */
  115.     if ( argc < 4 ) {
  116.         puts("usage: zres drive libname file1 ...");
  117.         exit() ;
  118.     }
  119.     if ( strchr(argv[2], '.') != 0 ) {
  120.         puts("library name should not have extension") ;
  121.         exit() ;
  122.     }
  123.  
  124.     /* open submit file */
  125.     if ( (Subfile=fopen("CLIB.SUB", "w")) == 0 ) {
  126.         fprintf(stderr, "Unable to open submit file\n") ;
  127.         exit() ;
  128.     }
  129.  
  130.     /* open object file for library modules */
  131.     if ( (Objfile=fopen("CLIB.OBJ", "w")) == 0 ) {
  132.         fprintf(stderr, "Unable to open CLIB.OBJ\n") ;
  133.         exit() ;
  134.     }
  135.  
  136.     /* start building command */
  137.     fprintf(Subfile, "zlink %s=", argv[3]) ;
  138.  
  139.     /* load all input files on command line */
  140.     i = 2 ;
  141.     while ( ++i < argc ) {
  142.         loadfile(argv[i]) ;
  143.         fprintf(Subfile, "%s,", argv[i]) ;
  144.     }
  145.     /* always load IOLIB.OBJ */
  146.     loadfile("iolib") ;
  147.     fprintf(Subfile, "IOLIB,CLIB\n") ;
  148.  
  149.     /* fetch library index */
  150.     strcpy(temp, argv[2]) ;
  151.     strcat(temp, ".IDX") ;
  152.     read_index(temp) ;
  153.  
  154.     /* open library */
  155.     strcpy(temp, argv[2]) ;
  156.     strcat(temp, ".LIB") ;
  157.     if ( (Libfile=fopen(temp, "r")) == 0 ) {
  158.         fprintf(stderr, "Unable to open library file\n") ;
  159.         exit() ;
  160.     }
  161.  
  162.  
  163.     /* process all as yet undefined symbols */
  164.     Plotflag = Printflag = Floatflag = Ploadflag = FALSE ;
  165.     Scanflag = Sloadflag = FALSE ;
  166.     /* loop until no more modules are loaded */
  167.     while ( pass() )
  168.         ;
  169.  
  170.     /* load required printf file */
  171.     if ( Printflag && !Ploadflag ) {
  172.         if ( Floatflag )
  173.             copy_module(find_module("PRINTF2")) ;
  174.         else
  175.             copy_module(find_module("PRINTF1")) ;
  176.     }
  177.     /* load required scanf file */
  178.     if ( Scanflag && !Sloadflag ) {
  179.         if ( Floatflag )
  180.             copy_module(find_module("SCANF2")) ;
  181.         else
  182.             copy_module(find_module("SCANF1")) ;
  183.     }
  184.  
  185.     /* tidy up any new unresolved symbols */
  186.     while ( pass() )
  187.         ;
  188.  
  189.     /* erase temporary library file */
  190.     fprintf(Subfile, "era clib.obj\n") ;
  191.  
  192.     if ( Plotflag ) {
  193.         /* add plot RSX if required */
  194.         fprintf(Subfile, "\ngencom %s plot\n", argv[3]) ;
  195.     }
  196.     /* copy .com file from M: and return to drive in 1st arg */
  197.     fprintf(Subfile, "%s\npip %s.COM=m:\nera m:clib.sub\n", argv[1], argv[3]) ;
  198.  
  199.     /* close CLIB.OBJ */
  200.     putb(2, Objfile) ;
  201.     putb(0, Objfile) ;
  202.  
  203.     fclose(Objfile) ;
  204.     fclose(Subfile) ;
  205.     fclose(Libfile) ;
  206.  
  207.     /* print usage statistics */
  208.     printf("\nSymbol table   %d/%d\n", Symused, NUMENT) ;
  209.     printf("Library table  %d/%d\n", Libused, LIBENT) ;
  210.     printf("Index table    %d/%d\n", Ixused, IXENT) ;
  211. }
  212.  
  213. /*
  214.  * pass - make one pass through symbols
  215.  * return true if a module was loaded
  216.  */
  217. pass()
  218. {
  219.     int module_loaded ;
  220.     char *cptr ;            /* pointer into symbol table */
  221.     char *lptr ;            /* pointer into library table */
  222.     char *mod ;                /* name of module being loaded */
  223.     int i ;
  224.         
  225.     module_loaded = FALSE ;
  226.     cptr = Symtab - SYMREC ;
  227.     /* loop for all records in table */
  228.     for ( i=0; i<NUMENT; ++i ) {
  229.         cptr += SYMREC ;
  230.         if ( cptr[NAME] != 0 && cptr[TYPE] == UNDEFINED ) {
  231.             if ( strcmp(cptr+NAME, "Q_PRINTF") == 0 ) {
  232.                 /* want to load _printf, but can't yet */
  233.                 Printflag = TRUE ;
  234.                 cptr[TYPE] = DEFINED ;
  235.                 continue ;
  236.             }
  237.             if ( strcmp(cptr+NAME, "Q_SCANF") == 0 ) {
  238.                 /* want to load _scanf, but can't yet */
  239.                 Scanflag = TRUE ;
  240.                 cptr[TYPE] = DEFINED ;
  241.                 continue ;
  242.             }
  243.             /* undefined symbol found, look in library */
  244.             lptr = search(cptr+NAME,STARTLIB,LIBREC,ENDLIB,LIBENT,LIBNAME) ;
  245.             if ( lptr == 0 || lptr[LIBNAME] == 0 ) {
  246.                 /* symbol not found in library index */
  247.                 if ( strcmp(cptr+NAME, "_END") != 0 ) {
  248.                     /* don't tell user _END is undefined, it always is */
  249.                     printf("%s is unresolved\n", cptr+NAME) ;
  250.                 }
  251.                 cptr[TYPE] = DEFINED ;
  252.             }
  253.             else {
  254.                 /* resolve reference by loading file */
  255.                 copy_module(lptr[MODULE]) ;
  256.                 mod = Module[lptr[MODULE]] ;
  257.                 if ( strcmp(mod,"PLOT") == 0 )
  258.                     Plotflag = TRUE ;
  259.                 else if ( strcmp(mod,"FLOAT") == 0 )
  260.                     Floatflag = TRUE ;
  261.                 else if ( strcmp(mod,"PRINTF2") == 0 )
  262.                     Ploadflag = TRUE ;
  263.                 else if ( strcmp(mod,"SCANF2") == 0 )
  264.                     Sloadflag = TRUE ;
  265.                 module_loaded = TRUE ;
  266.             }
  267.         }
  268.     }
  269.     return module_loaded ;
  270. }
  271.  
  272. /*
  273.  * loadfile - load symbols in given object file into symbol table
  274.  */
  275. loadfile(name)
  276. char *name ;
  277. {
  278.     char record[257];        /* record from object file */
  279.     int infile ;            /* file descriptor for input file */
  280.     int n ;                    /* number of bytes in record */
  281.  
  282.     /* open input file */
  283.     strcpy(record, name) ;
  284.     strcat(record, ".OBJ") ;
  285.     if ( (infile=fopen(record,"r")) == 0 ) {
  286.         fprintf(stderr, "Unable to open input file: %s\n", record) ;
  287.         exit();
  288.     }
  289.  
  290.     /* examine all records in file */
  291.     while ( (n=getrec(record,infile)) ) {
  292.         if ( record[0] == 4 ) {
  293.             /* symbol record */
  294.             record[n] = 0 ;
  295.             if ( (record[1] & 6) == 6 ) {
  296.                 /* global symbol defined in this file */
  297.                 addsym(&record[4],DEFINED);
  298.             }
  299.             else if ( !(record[1] & 2) ) {
  300.                 /* symbol is external */
  301.                 addsym(&record[4],UNDEFINED);
  302.             }
  303.         }
  304.     }
  305.  
  306.     fclose(infile);
  307. }
  308.  
  309. /*
  310.  * read index file and set up library table and index table
  311.  */
  312. read_index(name)
  313. char *name ;        /* name of index file */
  314. {
  315.     int infile ;            /* input file descriptor */
  316.     char temp[80];            /* temporary string to hold input */
  317.     int last ;                /* number of last module */
  318.     char *nxtptr ;            /* pointer to next empty location in index */
  319.     int n, i ;
  320.  
  321.     /* read library index */
  322.     if ( (infile=fopen(name, "r")) == 0 ) {
  323.         puts("cannot open index file");
  324.         exit();
  325.     }
  326.  
  327.     /* find number of modules */
  328.     n = 0 ;
  329.     while ( getline(infile, temp) && strlen(temp) != 0 ) {
  330.         ++n ;
  331.     }
  332.     Nmod = n ;
  333.  
  334.     /* rewind file */
  335.     xseek(infile, 0, 0) ;
  336.  
  337.     /* read module names */
  338.     Module = zalloc( sizeof(int)*n ) ;
  339.     Objptr = zalloc( sizeof(int)*n ) ;
  340.     Rec = zalloc(sizeof(int)*n) ;
  341.     Off = zalloc(sizeof(int)*n) ;
  342.  
  343.     for ( i=0; i<n; ++i ) {
  344.         Module[i] = alloc(13) ;
  345.         if (fscanf(infile, "%s %d %d", Module[i], &Rec[i], &Off[i]) != 3 ) {
  346.             puts("index read error") ;
  347.             exit() ;
  348.         }
  349.     }
  350.     printf("bytes free: %u\n", avail() ) ;
  351.  
  352.     /* discard null line */
  353.     getline(infile, temp) ;
  354.  
  355.     /* fetch index of functions and put them in table */
  356.     nxtptr = Index - IXREC ;
  357.     last = 0 ;
  358.     while ( fscanf(infile, "%s %d", temp, &n) == 2 ) {
  359.         if ( abs(n) != last ) {
  360.             /* new module coming in now */
  361.             last = abs(n) ;
  362.             /* leave null entry to mark end of previous chain */
  363.             nxtptr += IXREC ;
  364.             ++Ixused ;
  365.             Objptr[last-1] = nxtptr ;
  366.         }
  367.         /* add symbol to index */
  368.         strcpy(nxtptr+IXNAME, temp) ;
  369.         if ( n > 0 ) {
  370.             nxtptr[IXTYPE] = DEFINED ;
  371.             /* add defined symbol to library table */
  372.             addlib(temp, (n-1)) ;
  373.         }
  374.         else
  375.             nxtptr[IXTYPE] = UNDEFINED ;
  376.         nxtptr += IXREC ;
  377.         ++Ixused ;
  378.         if ( Ixused > IXENT-1 ) {
  379.             printf("index table full\n") ;
  380.             exit() ;
  381.         }
  382.     }
  383.     fclose(infile);
  384. }
  385.  
  386. /*
  387.  * resolve references to given module
  388.  */
  389. resolve(n)
  390. int n ;            /* number of file in Objptr table */
  391. {
  392.     char *nxtptr ;        /* pointer to next symbol in chain */
  393.  
  394.     nxtptr = Objptr[n] ;
  395.     /* read down index chain */
  396.     while ( nxtptr[IXNAME] ) {
  397.         addsym(&nxtptr[IXNAME], nxtptr[IXTYPE]) ;
  398.         nxtptr += IXREC ;
  399.     }
  400. }
  401.  
  402. /*
  403.  * fetch record from file
  404.  * return number of valid bytes, 0 for end of module
  405.  */
  406. getrec(ptr,fd)
  407. char *ptr ;
  408. int fd ;
  409. {
  410.     int j ;                /* number of bytes returned in record */
  411.     int i ;                /* count number of bytes from file */
  412.  
  413.     i = getb(fd) ;
  414.     if ( i == 2 || i == -1 ) {
  415.         return 0 ;
  416.     }
  417.     j = (--i) & 0xff ;
  418.     while ( i-- ) {
  419.         *ptr++ = getb(fd) ;
  420.     }
  421.     return j ;
  422. }
  423.  
  424. addsym(str,type)
  425. char *str ;
  426. int type ;
  427. {
  428.     char *cptr ;
  429.  
  430.     cptr = search(str, STARTTAB, SYMREC, ENDTAB, NUMENT, NAME) ;
  431.     if ( cptr == 0 ) {
  432.         puts("symbol table full\n");
  433.         exit();
  434.     }
  435.     if ( *cptr != 0 ) {
  436.         /* symbol found */
  437.         if ( type == DEFINED ) {
  438.             /* definition found for symbol */
  439.             cptr[TYPE] = DEFINED ;
  440.         }
  441.     }
  442.     else {
  443.         /* symbol not found, add it to table */
  444.         strcpy(cptr+NAME, str);
  445.         cptr[TYPE] = type ;
  446.         ++Symused ;
  447.     }
  448. }
  449.  
  450. addlib(str,modx)
  451. char *str ;                /* symbol to put in table */
  452. int modx ;                /* index of module where symbol is found */
  453. {
  454.     char *cptr ;
  455.  
  456.     cptr = search(str, STARTLIB, LIBREC, ENDLIB, LIBENT, LIBNAME) ;
  457.     if ( cptr == 0 ) {
  458.         puts("library symbol table full") ;
  459.         exit() ;
  460.     }
  461.     /* add symbol to table (overwriting previous contents) */
  462.     strcpy(cptr+LIBNAME, str) ;
  463.     cptr[MODULE] = modx ;
  464.     ++Libused ;
  465. }
  466.  
  467. /*
  468.  * search for symbol match in table
  469.  * returns pointer to slot found or empty slot
  470.  * returns zero if table full
  471.  */
  472. search(sname, buf, len, end, max, off)
  473. char *sname ;        /* symbol to search for */
  474. char *buf ;            /* start of table */
  475. int len ;            /* length of record */
  476. char *end ;            /* end of table */
  477. int max ;            /* number of entries in table */
  478. int off ;            /* offset of symbol within record */
  479. {
  480.     char *cptr, *cptr2 ;
  481.  
  482.     cptr = cptr2 = buf + ( (hash(sname)%(max-1)) * len ) ;
  483.     while ( *cptr != 0 ) {
  484.         if ( strncmp(sname, cptr+off, NAMEMAX) == 0 ) {
  485.             /* match, return pointer */
  486.             return cptr ;
  487.         }
  488.         if ( (cptr+=len) >= end ) {
  489.             /* past end of table */
  490.             cptr = buf ;
  491.         }
  492.         if ( cptr == cptr2 ) {
  493.             /* have gone full circle, table full */
  494.             return 0 ;
  495.         }
  496.     }
  497.     /* have found empty slot, return pointer to it */
  498.     return cptr ;
  499. }
  500.  
  501. /*
  502.  * hash function for table search
  503.  */
  504. hash(sname)
  505. char *sname ;
  506. {
  507.     int i, c ;
  508.  
  509.     i = 0 ;
  510.     while ( (c=*sname++) ) i = (i << 2) + c ;
  511.     return abs(i) ;
  512. }
  513.  
  514. /*
  515.  * zalloc - allocate memory and zero it
  516.  *
  517.  * zalloc(count)
  518.  */
  519. #asm
  520. qzalloc: pop hl        ;return address
  521.     pop bc            ;character count
  522.     push bc
  523.     push hl
  524.     push bc            ;character count as arg to alloc()
  525.     call qalloc        ;HL points to allocated memory
  526.     pop bc            ;count
  527.     dec bc            ;adjust count
  528.     push hl            ;save pointer to allocated memory
  529.     ld (hl),0        ;start zeroing block
  530.     ld d,h            ;DE points on byte after HL
  531.     ld e,l
  532.     inc de
  533.     ldir            ;zero block
  534.     pop hl            ;retrieve block pointer
  535.     ret
  536. #endasm
  537.  
  538. /*
  539.  * find index of module name corresponding to given string
  540.  */
  541. find_module(string)
  542. char *string ;
  543. {
  544.     int i ;
  545.  
  546.     for ( i=0; i<Nmod; ++i ) {
  547.         if ( strcmp(Module[i], string) == 0 ) {
  548.             return i ;
  549.         }
  550.     }
  551.     return -1 ;
  552. }
  553.  
  554. /*
  555.  * copy_module - copy module from library to temporary .obj file
  556.  */
  557. copy_module(modx)
  558. int modx ;            /* index of module to be copied */
  559. {
  560.     int j, i ;
  561.  
  562.     if ( modx == -1 )
  563.         printf("Unable to find module\n") ;
  564.     else {
  565.         /* resolve references */
  566.         resolve(modx) ;
  567.         printf("Copying %s\n", Module[modx]) ;
  568.         putb(3, Objfile) ;
  569.         putb(1, Objfile) ;
  570.         putb(0, Objfile) ;
  571.         if ( xseek(Libfile, Rec[modx], Off[modx]) != 0 ) {
  572.             fprintf(stderr, "seek failure\n") ;
  573.             exit() ;
  574.         }
  575.         /* copy all records from library to clib.obj */
  576.         while ( (i=getb(Libfile)) != 2 ) {
  577.             /* loop while not end of module record */
  578.             if ( i == -1 ) {
  579.                 /* break on end of file */
  580.                 break ;
  581.             }
  582.             if ( (j=getb(Libfile)) == 1 ) {
  583.                 /* break on start of next module */
  584.                 break ;
  585.             }
  586.             putb(i--, Objfile) ;
  587.             putb(j, Objfile) ;
  588.             while ( --i ) {
  589.                 putb(getb(Libfile), Objfile) ;
  590.             }
  591.         }
  592.         putb(2, Objfile) ;
  593.         putb(1, Objfile) ;
  594.     }
  595. }
  596.  
  597. /*
  598.  * getline - fetch line from input channel
  599.  *           puts line at pointer, returns FALSE on end of file
  600.  *           returns TRUE for successful get
  601.  */
  602. getline( fd, pointer )
  603. int fd ;
  604. char *pointer ;
  605. {
  606.     int ch ;
  607.  
  608.     while ( (ch=getc(fd)) != EOF ) {
  609.         if( ch == CR ) {
  610.             *pointer = NULL ;
  611.             return TRUE ;
  612.         }
  613.         else
  614.             *pointer++ = ch ;
  615.     }
  616.     *pointer = NULL ;
  617.     return FALSE ;
  618. }
  619.  
  620. extern _fchk(), _ffcb[], _ffirst[], _flast[], _fnext[] ;
  621.  
  622. #define MREAD 22489
  623.  
  624. /*
  625.  * seek to given record, and byte offset within record
  626.  * only works for read, record is absolute from start of file
  627.  * return -1 on error, 0 on success
  628.  */
  629. xseek(fd, rec, off)
  630. int fd, rec, off ;
  631. {
  632.     int index, *rrn ;
  633.     char *fcb ;
  634.  
  635.     index = fd - 5 ;
  636.     if ( _fchk(index) != MREAD )
  637.         return -1 ;
  638.     fcb = _ffcb[index] ;
  639.     rrn = &fcb[33] ;
  640.     *rrn = rec ;
  641.     cpm(26, _ffirst[index]) ;        /* set DMA */
  642.     if ( cpm(33, fcb) ) {            /* perform random read */
  643.         cpm(26, 128) ;
  644.         return -1 ;
  645.     }
  646.     cpm(26, 128) ;                    /* reset DMA */
  647.     /* force refresh of buffer */
  648.     _fnext[index] = _flast[index] ;
  649.     /* move forward by offset */
  650.     while ( off-- ) {
  651.         getb(fd) ;
  652.     }
  653.     return 0 ;
  654. }
  655.